package service

import (
	"archive/zip"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"project-deploy-service/models" // 请确保路径正确
	"project-deploy-service/utils"
	"time"
)

type fileService struct {
}

var FileService fileService

// UploadHandler 上传文件和对象的处理函数，自动备份文件
func (fu *fileService) UploadHandler(c *gin.Context) {
	var err error
	var config models.Config             //初始化配置项
	var project *models.Project          //初始化项目实体
	var historyModel models.HistoryModel //初始化文件保存记录
	// 获取 JSON 对象
	var obj models.ReceiveFileModel
	obj.Msg = c.PostForm("msg")
	obj.Identifier = c.PostForm("identifier")
	obj.Filename = c.PostForm("filename")
	//获取项目配置列表
	config = utils.FileUtil.LoadConfig()

	//匹配项目
	project = matchProject(config, obj, c)
	if project == nil {
		c.String(http.StatusBadRequest, "无法匹配项目！")
		return
	}
	fullPath := project.Path            //获取文件路径
	filename := filepath.Base(fullPath) //读取文件名
	historyModel.CreateTime = now()
	historyModel.Name = project.Filename
	historyModel.Msg = obj.Msg
	//重命名文件
	backup(fullPath, filename, &historyModel)

	if project.Type == "1" {
		//如果是前端，传递过来的是zip文件 所以要解压缩

		newFile := fullPath + ".zip"
		// 创建目标文件
		targetPath := filepath.Join(newFile)
		//保存zip文件
		err = utils.FileUtil.SaveToFile(targetPath, c)
		if err != nil {
			c.String(http.StatusBadRequest, fmt.Sprintf("执行失败: %s", err.Error()))
		}

		//解压缩
		err = utils.FileUtil.Unzip(newFile, filepath.Dir(fullPath))
		if err != nil {
			c.String(http.StatusBadRequest, fmt.Sprintf("执行失败: %s", err.Error()))
			return
		}
		folderName := readFolderName(newFile)

		unzipName := filepath.Join(filepath.Dir(fullPath), folderName)
		if unzipName != fullPath {
			err := os.Rename(unzipName, fullPath)
			if err != nil {
				c.String(http.StatusBadRequest, fmt.Sprintf("执行失败: %s", err.Error()))
				return
			}
		}
		//解压成功后删除文件
		err := os.Remove(newFile)
		if err != nil {
			fmt.Println("Error deleting file:", err)
		}
	} else if project.Type == "2" {
		//如果是后端 直接保存就行

		// 创建目标文件
		targetPath := filepath.Join(fullPath)
		err = utils.FileUtil.SaveToFile(targetPath, c)
		if err != nil {
			c.String(http.StatusBadRequest, fmt.Sprintf("执行失败: %s", err.Error()))
		}
	}
	if err == nil {
		HistoryService.Insert(historyModel)
	}

}

// 检测项目是否存在
func matchProject(config models.Config, obj models.ReceiveFileModel, c *gin.Context) *models.Project {
	MachineId := c.GetHeader("X-Fingerprint")

	for _, v := range config.ProjectList {
		if !utils.ListUtil.In(v.MachineId, MachineId) {
			//匹配机器码
			continue
		}
		if v.Identifier != "" {
			//如果有项目识别码 则匹配识别码
			if v.Identifier == obj.Identifier {
				return &v
			}
		} else if v.Filename == obj.Filename {
			//否则匹配项目名
			return &v
		}
	}
	return nil
}

// 备份项目
func backup(fullPath string, filename string, historyModel *models.HistoryModel) {
	newPath, err := utils.FileUtil.BackupFile(fullPath, utils.FileUtil.RemoveFileExtension(filename)+"_"+now())
	if err != nil {
		fmt.Println(err)
	} else {
		historyModel.Path = newPath
	}
}
func now() string {
	return time.Now().Format("2006-01-02-150405")
}
func readFolderName(zipPath string) string {
	zipFile, err := os.Open(zipPath)
	if err != nil {
		log.Fatalf("Failed to open ZIP file: %v", err)
	}
	defer func(zipFile *os.File) {
		err := zipFile.Close()
		if err != nil {
			return
		}
	}(zipFile)

	// 读取 ZIP 文件
	fileInfo, err := zipFile.Stat()
	if err != nil {
		log.Fatalf("Failed to get file info: %v", err)
	}
	zipReader, err := zip.NewReader(zipFile, fileInfo.Size())
	if err != nil {
		log.Fatalf("Failed to read ZIP file: %v", err)
	}
	// 遍历 ZIP 文件中的所有文件条目
	for _, file := range zipReader.File {
		// 获取文件条目的名称
		name := file.Name

		// 使用 filepath.Dir 获取条目的父目录
		dir := filepath.Dir(name)

		// 检查条目是否为目录（目录条目以斜杠结尾）
		if file.FileInfo().IsDir() {
			// 打印第一个文件夹名称并退出
			fmt.Println("First directory:", dir)
			return dir
		}
	}

	return ""
}
